import EventManage from "../event/EventManage";
import EventType from "../../model/EventType";
import TimeManage from "../time/TimerManage";
import BaseUI from "./BaseUI";
import { LayerUI } from "./LayerUI";
import UIConfig from "../config/UIConfig";
import { ClassView } from "./UIDefine";
import Singleton from "../context/Singleton";
import { Logger } from "../log/logger";
import Utils from "../utils/Utils";

export default class UIManage extends Singleton {

    private _allui = new Map<number, UIInfo>();

    private _sceneLayer: LayerUI;

    private _viewLayer: LayerUI;

    private _topLayer: LayerUI;

    private _effLayer: LayerUI;

    private _guideLayer: LayerUI;


    public constructor() {
        super();
        Laya.timer.loop(UIConfig.detectionTick, this, this.$onDetectionTick);
        EventManage.I.on(EventType.CLOSE_UI, this, this.closeUI);
    }

    openScene<D extends Laya.Scene, T extends BaseUI<D>>(ui: ClassView<D, T>, ages?: any) {
        this.openUI(ui, this.sceneLayer, ages);
    }

    popup<D extends Laya.Scene, T extends BaseUI<D>>(ui: ClassView<D, T>, ages?: any) {
        this.openUI(ui, this.viewLayer, ages);
    }

    openTop<D extends Laya.Scene, T extends BaseUI<D>>(ui: ClassView<D, T>, ages?: any) {
        this.openUI(ui, this.topLayer, ages);
    }


    openUI<D extends Laya.Scene, T extends BaseUI<D>>(ui: ClassView<D, T>, layer: LayerUI, ages: any) {
        let uiinfo = this.getOrCreateUIinfo(ui);
        uiinfo.layer = layer;
        uiinfo.bindui = ui;
        uiinfo.openTime = TimeManage.I.second;
        if (Utils.isNil(uiinfo.instance)) {
            uiinfo.instance = new ui();
        }
        uiinfo.instance["_data"] = ages;
        uiinfo.instance.open()
        layer.add(uiinfo.gid, uiinfo.instance)
    }

    closeUI<D extends Laya.Scene, T extends BaseUI<D>>(ui: ClassView<D, T> | number, c: any) {
        let uiinfo = this.getOrCreateUIinfo(ui);
        if (uiinfo.instance) {
            uiinfo.instance.closeSelf(c);
            if (uiinfo.layer) {
                uiinfo.layer.remove(uiinfo.instance);
            } else {
                uiinfo.clear();
            }

            uiinfo.closeTime = TimeManage.I.second;
        }
    }


    //L1,常驻层（游戏中至少有一个scene）
    get sceneLayer() {
        if (!this._sceneLayer) {
            let layer = this._sceneLayer = new LayerUI("sceneLayer");
            layer.zOrder = 0;
            // layer.size(Laya.stage.width, Laya.stage.height);
            Laya.stage.addChild(layer);

        }

        return this._sceneLayer;
    }

    //L2，游戏弹窗层
    get viewLayer() {
        if (!this._viewLayer) {
            let layer = this._viewLayer = new LayerUI("viewLayer");
            layer.zOrder = 1;
            // layer.size(Laya.stage.width, Laya.stage.height);
            Laya.stage.addChild(layer);
        }

        return this._viewLayer;
    }

    //L3，top层
    get topLayer() {
        if (!this._topLayer) {
            let layer = this._topLayer = new LayerUI("topLayer");
            layer.zOrder = 2;
            // layer.size(Laya.stage.width, Laya.stage.height);
            Laya.stage.addChild(layer);
        }

        return this._topLayer;
    }

    //L4，特效层
    get effLayer() {
        if (!this._effLayer) {
            let layer = this._effLayer = new LayerUI("effLayer");
            layer.zOrder = 3
            // layer.size(Laya.stage.width, Laya.stage.height);
            layer.mouseEnabled = false;
            Laya.stage.addChild(layer);
        }

        return this._effLayer;
    }

    //L5，引导层
    get guideLayer() {
        if (!this._guideLayer) {
            let layer = this._guideLayer = new LayerUI("guideLayer");
            layer.zOrder = 4
            // layer.size(Laya.stage.width, Laya.stage.height);
            Laya.stage.addChild(layer);
        }

        return this._guideLayer;
    }

    private getOrCreateUIinfo<D extends Laya.Scene, T extends BaseUI<D>>(ui: ClassView<D, T> | number) {
        let gid = typeof ui === "number" ? ui : ui["GID"]();
        if (this._allui.has(gid)) {
            return this._allui.get(gid);
        } else {
            this._allui.set(gid, new UIInfo(gid, ui));
        }

        return this._allui.get(gid);
    }

    private $onDetectionTick() {
        this._allui.forEach(_check.bind(this))

        function _check(v: UIInfo, k) {
            if (!v.instance || v.instance.opened) return;
            if (TimeManage.I.second - v.closeTime > UIConfig.viewPeriod) {
                Logger.logView(v, "清除view")
                v.clear();
            }
        }
    }
}

class UIInfo {

    /**唯一标识 */
    gid: number;

    /**view实列 */
    instance: BaseUI<any>;

    /**绑定View */
    bindui: ClassView<any, BaseUI<any>>;

    /**属于层级 */
    layer: LayerUI;

    /**打开时间戳 */
    openTime: number = -1;

    /**关闭时间戳 */
    closeTime: number = -1;

    constructor(gid: number, bindui: any) {
        this.gid = gid;
        this.bindui = bindui;
    }

    clear() {
        if (this.instance) {
            this.instance.destory();
            this.instance = null;
        }

        this.layer = null;
        this.openTime = -1;
        this.closeTime = -1;
    }

}